/**
 * RESTful API 适配器
 * 针对标准RESTful API的请求处理适配器
 */

class RestfulAdapter {
  constructor(config = {}) {
    this.config = config;
  }

  /**
   * 设置配置
   * @param {Object} config 适配器配置
   */
  setConfig(config) {
    this.config = {
      ...this.config,
      ...config
    };
  }

  /**
   * 发送请求
   * @param {Object} config 请求配置
   * @returns {Promise} 请求Promise
   */
  request(config) {
    return new Promise((resolve, reject) => {
      // 构建请求选项
      const options = this._buildRequestOptions(config);
      
      // 创建AbortController以支持取消请求
      const controller = new AbortController();
      if (!options.signal) {
        options.signal = controller.signal;
      }
      
      // 创建请求超时
      let timeoutId = null;
      if (config.timeout) {
        timeoutId = setTimeout(() => {
          controller.abort();
          const error = new Error('Request timeout');
          error.name = 'TimeoutError';
          reject(error);
        }, config.timeout);
      }
      
      // 发送请求
      const requestPromise = this._sendRequest(options)
        .then(response => {
          // 清除超时
          if (timeoutId) {
            clearTimeout(timeoutId);
          }
          
          return response;
        })
        .then(response => {
          // 处理响应
          return this._handleResponse(response, config);
        })
        .then(result => {
          resolve(result);
        })
        .catch(error => {
          // 清除超时
          if (timeoutId) {
            clearTimeout(timeoutId);
          }
          
          // 处理错误
          this._handleError(error, config, reject);
        });
      
      // 添加abort方法以支持取消
      requestPromise.abort = (reason) => {
        controller.abort(reason);
      };
      
      return requestPromise;
    });
  }

  /**
   * 构建请求选项
   * @param {Object} config 请求配置
   * @returns {Object} 请求选项
   * @private
   */
  _buildRequestOptions(config) {
    // 合并baseURL和URL
    const url = this._resolveUrl(config.baseURL, config.url);
    
    // 构建带查询参数的URL
    const finalUrl = this._appendQueryParams(url, config.params);
    
    // 准备请求头
    const headers = {
      ...this.config.headers,
      ...config.headers
    };
    
    // 如果有请求体且未指定Content-Type，设置默认值
    if (config.data && !headers['Content-Type'] && !headers['content-type']) {
      headers['Content-Type'] = 'application/json';
    }
    
    // 构建请求选项
    const options = {
      method: (config.method || 'GET').toUpperCase(),
      headers,
      signal: config.signal
    };
    
    // 添加请求体
    if (config.data && options.method !== 'GET' && options.method !== 'HEAD') {
      if (
        (headers['Content-Type'] || headers['content-type'])?.includes('application/json') &&
        typeof config.data === 'object'
      ) {
        options.body = JSON.stringify(config.data);
      } else if (config.data instanceof FormData) {
        options.body = config.data;
        // 删除Content-Type，让浏览器自动设置
        delete options.headers['Content-Type'];
        delete options.headers['content-type'];
      } else {
        options.body = config.data;
      }
    }
    
    return {
      url: finalUrl,
      options
    };
  }

  /**
   * 解析URL
   * @param {String} baseURL 基础URL
   * @param {String} url 请求URL
   * @returns {String} 完整URL
   * @private
   */
  _resolveUrl(baseURL, url) {
    if (!url) {
      return baseURL || '';
    }
    
    // 如果url是绝对URL，直接返回
    if (url.startsWith('http://') || url.startsWith('https://')) {
      return url;
    }
    
    // 如果没有baseURL，返回url
    if (!baseURL) {
      return url;
    }
    
    // 合并baseURL和url
    return baseURL.endsWith('/') 
      ? baseURL + (url.startsWith('/') ? url.substring(1) : url)
      : (baseURL + (url.startsWith('/') ? url : '/' + url));
  }

  /**
   * 附加查询参数
   * @param {String} url URL
   * @param {Object} params 查询参数
   * @returns {String} 带查询参数的URL
   * @private
   */
  _appendQueryParams(url, params) {
    if (!params || Object.keys(params).length === 0) {
      return url;
    }
    
    const queryString = Object.entries(params)
      .filter(([_, value]) => value !== undefined && value !== null)
      .map(([key, value]) => {
        // 数组参数特殊处理
        if (Array.isArray(value)) {
          return value
            .map(item => `${encodeURIComponent(key)}=${encodeURIComponent(item)}`)
            .join('&');
        }
        return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
      })
      .join('&');
    
    // 添加查询参数
    if (queryString) {
      return url.includes('?') 
        ? `${url}&${queryString}`
        : `${url}?${queryString}`;
    }
    
    return url;
  }

  /**
   * 发送请求
   * @param {Object} options 请求选项
   * @returns {Promise} 请求Promise
   * @private
   */
  async _sendRequest({ url, options }) {
    try {
      // 发送请求
      const response = await fetch(url, options);
      return response;
    } catch (error) {
      // 处理网络错误
      if (error.name === 'AbortError') {
        const abortError = new Error('Request aborted');
        abortError.name = 'AbortError';
        throw abortError;
      }
      
      const networkError = new Error(error.message || 'Network error');
      networkError.name = 'NetworkError';
      networkError.originalError = error;
      throw networkError;
    }
  }

  /**
   * 处理响应
   * @param {Response} response Fetch响应对象
   * @param {Object} config 请求配置
   * @returns {Promise} 处理后的响应Promise
   * @private
   */
  async _handleResponse(response, config) {
    // 提取响应头
    const headers = {};
    response.headers.forEach((value, key) => {
      headers[key] = value;
    });
    
    // 提取响应体
    let data;
    try {
      // 根据响应类型解析数据
      const responseType = config.responseType || 'json';
      
      if (responseType === 'json') {
        // 尝试解析为JSON
        const text = await response.text();
        try {
          data = text ? JSON.parse(text) : null;
        } catch (e) {
          // 如果解析失败，返回原始文本
          data = text;
        }
      } else if (responseType === 'text') {
        data = await response.text();
      } else if (responseType === 'arraybuffer') {
        data = await response.arrayBuffer();
      } else if (responseType === 'blob') {
        data = await response.blob();
      } else {
        // 默认尝试JSON解析
        data = await response.json();
      }
    } catch (error) {
      // 如果响应体解析失败，设置为null
      data = null;
    }
    
    // 构建响应对象
    const result = {
      data,
      status: response.status,
      statusText: response.statusText,
      headers,
      config,
      request: {
        url: response.url,
        redirected: response.redirected,
        type: response.type
      }
    };
    
    // 检查响应状态
    const validateStatus = config.validateStatus || this.config.validateStatus;
    if (validateStatus && validateStatus(response.status)) {
      return result;
    }
    
    // 如果响应状态无效，抛出错误
    const error = new Error(`Request failed with status code ${response.status}`);
    error.response = result;
    error.status = response.status;
    error.statusText = response.statusText;
    throw error;
  }

  /**
   * 处理错误
   * @param {Error} error 错误对象
   * @param {Object} config 请求配置
   * @param {Function} reject Promise的reject函数
   * @private
   */
  _handleError(error, config, reject) {
    // 增强错误对象
    if (!error.config) {
      error.config = config;
    }
    
    // 特殊处理AbortError，用于取消请求
    if (error.name === 'AbortError') {
      error.message = 'Request canceled';
      error.canceled = true;
    }
    
    // 拒绝Promise
    reject(error);
  }
}

// 添加具名导出
export { RestfulAdapter };
export default RestfulAdapter; 